/*
简单零碎接口的实现：
    1. 日志宏的实现
    2. Json序列化和反序列化的实现
    3. uuid的生成
*/

#pragma once

#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <random>
#include <sstream>
#include <atomic>
#include <iomanip>

namespace RpcModule
{
    // 1. ------------------------------ 日志宏的实现 ---------------------------------------
#define LEVELDEBUG 0
#define LEVELINFO 1
#define LEVELERROR 2
#define LEVELFATAL 3

#define LEVELDEFAULT LEVELDEBUG

// 结果为：[2025-11-01 15:29:05] [test.cc:6]       hello world-11
// \ -- 转义符，一个宏语句必须在一行，这里是将换行转义，表示还是同一行
// ... -- 不定参，使用__VA_ARGS__接收参数
// ##__VA_ARGS__ -- 两个#，如果没有参数，取消前面的逗号
// 获取时间 -- 不再讲这里，自己看
#define LOG(level, format, ...)                                                                \
    if (level >= LEVELDEFAULT)                                                                 \
    {                                                                                          \
        do                                                                                     \
        {                                                                                      \
            time_t timestamp = time(NULL);                                                     \
            struct tm *lt = localtime(&timestamp);                                             \
            char time_tmp[32] = {0};                                                           \
            strftime(time_tmp, 31, "%Y-%m-%d %T", lt);                                         \
            printf("[%s] [%s:%d]\t" format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        } while (0);                                                                           \
    }

#define LOGDEBUG(format, ...) LOG(LEVELDEBUG, format, ##__VA_ARGS__)
#define LOGINFO(format, ...) LOG(LEVELINFO, format, ##__VA_ARGS__)
#define LOGERROR(format, ...) LOG(LEVELERROR, format, ##__VA_ARGS__)
#define LOGFATAL(format, ...) LOG(LEVELFATAL, format, ##__VA_ARGS__)

    // 2. ------------------------ Json序列化/反序列化接口的实现 --------------------------------
    class JSON
    {
    public:
        // JsonCpp的序列化操作实现
        // 将val序列化，序列化之后的字符串写入到body中
        static bool Serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 1. 需要先创建一个StreamWriter的构造者类
            Json::StreamWriterBuilder writerbuilder;
            std::unique_ptr<Json::StreamWriter> swriter(writerbuilder.newStreamWriter());
            // 2. 然后就可以进行序列化操作了
            int ret = swriter->write(val, &ss);
            if (ret != 0)
            {
                LOGERROR("%s", "Json Serialize write failed!");
                return false;
            }
            body = ss.str();
            return true;
        }
        // JsonCpp的反序列化操作实现
        // 将body字符串反序列化，到val中
        static bool UnSerialize(const std::string body, Json::Value &val)
        {
            // 1. 先创建构造这类
            Json::CharReaderBuilder readerbuilder;
            std::unique_ptr<Json::CharReader> creader(readerbuilder.newCharReader());
            // 2. 直接进行反序列化操作
            std::string errs;
            bool ret = creader->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false)
            {
                LOGERROR("%s %s", "Unserialize parse failed! errs: ", errs.c_str());
                return false;
            }
            return true;
        }
    };

    // 2. -------------------------------- UUID的生成 ---------------------------------------
    class UUID
    {
    public:
        static std::string GetUuid()
        {
            // 1. 构造一个机器随机数对象
            std::random_device rd;
            // 2. 将随机数作为种子，构造伪随机数对象
            // 因为采取的是固定算法生成的随机数，所以如果种子相同
            // 生成的随机数就相同，所以是伪随机数
            std::mt19937 generator(rd());
            // 3. 限定随机数的范围
            std::uniform_int_distribution<int> distribution(0, 255);
            // 4. 生成八个随机数，按照16进制输入到数据流中
            std::stringstream ss;
            for (int i = 0; i < 8; i++)
            {
                // 550e8400-e29b-41d4
                if (i == 4 || i == 6)
                    ss << "-";
                // setfill -- 告诉下一个按宽度输出的字段，如果位数不够，填充0
                // setw -- 限制输出宽度
                // hex -- 按照16进制输出
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";
            // 5. 生成后续的16字节
            // 这里的seq为静态的原因：如果生成的随机数相同，从序号1开始增加
            // 只要保证序号的原子性，那么就肯定可以保证随机数的唯一性！
            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for (int i = 7; i >= 0; i--)
            {
                // 00 00 00 00 00 00 00 01
                // 先从00开始拿，因为看着舒服
                if (i == 5)
                    ss << "-";
                // 每次获取八位，先获取00，再获取00，最后获取01
                // ss中：00 00 00 00 00 00 00 01
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
            }
            // 返回的结果为：550e8400-e29b-41d4-0000-000000000001
            return ss.str();
        }
    };
}